bits 16
org 0x10000
loader_start:

    mov ax,cs
    mov ds,ax
    mov es,ax
    mov ax,0
    mov ss,ax
    mov fs,ax
    mov gs,ax
    mov sp,0x7c00
    mov bp,0x7c00

    push 3
    push 22
    push loader_msg
    call logprint
    add sp ,6

;open a20
    in al,0x92
    or al,00000010b
    out 0x92,al



    cli
    lgdt [gdtinfo]

;https://f.osdev.org/viewtopic.php?t=2115#:~:text=The%20trick%20is%20to%20set,are%20handled%20differently%20in%20PMode.  
;switch unreal mode
;The trick is to set up a GDT with 4GB segments and load them when you are in PMode. 
;The segment registers have a visible part containing the segment selector and
;an invisible part containing linear base address, limit, access rights etc.
;The invisible part is updated when a new segment selector is loaded. 
;This way you can load them with 4GB segments and go back to real mode, 
;keeping the segment register values. (Make sure not to load segment registers after going back.)
;Well, switching to PMode and back is essentially toggling the PE bit (bit 0) in CR0. 
;To enable PMode, set this bit and make a far jump to a 32bit address. 
;Load DS-GS with some selectors. 
;To go back to real mode, clear this bit and make another far jump to a 16bit real mode address. 
;Make sure to disable interrupts during this procedure since they are handled differently in PMode.
;switch protect mode
    mov eax,cr0
    or  eax,1
    mov cr0,eax

    jmp 0x8:pmode

pmode:
    
; bits 3-15 in the segment registers represent an index into the global descriptor table. 
; this is why mov ax,16(0b00000000 00010000)
    mov ax,16

    mov fs,ax

    mov eax,cr0
    and eax,11111110b

    mov cr0,eax
    jmp 0x1000:unrealmode


unrealmode:

    sti
    ; mov ebx,0x10000000
    ; mov ax,0x8899
    ; mov word [fs:ebx] ,ax
    jmp $
;https://wiki.osdev.org/Unreal_Mode
;https://wiki.osdev.org/Global_Descriptor_Table

%include "gen_unrealmodgdt.asm"
; gdtinfo:
;    dw gdt_end - gdt - 1   ;last byte in table
;    dd gdt


; align 16
; gdt:        
;     dd 0,0        ; entry 0 is always unused
; codedesc:
       
;     db 0xff, 0xff, 0x0000, 0, 1, 10011010b, 00000000b, 0
; flatdesc:   
;     db 0xff, 0xff, 0x0000, 0, 1, 10010010b, 11001111b, 0
; gdt_end:

    jmp $

loader_msg:
    db "MarkJiOS loader start!"

%include "step2_logprint.asm"